<?php

# http://projects:8081/cdapp-2kt-api/api/agent_atcos_load.php

include_once '_portal.php';

define('MODULE', isset($_GET['module']) ? $_GET['module'] : (isset($_GET['m']) ? $_GET['m'] : '*'));
define('LOG', isset($_GET['log']) ? $_GET['log'] : (isset($_GET['l']) ? $_GET['l'] : 0));
define('FORCE', isset($_GET['force']) ? intval($_GET['force']) : (isset($_GET['f']) ? intval($_GET['f']) : 0));
define('VERBOSE', isset($_GET['verbose']) ? intval($_GET['verbose']) : (isset($_GET['v']) ? intval($_GET['v']) : 0));
define('DEF_START_TIME', isset($_GET['start']) ? urldecode($_GET['start']) : (isset($_GET['s']) ? urldecode($_GET['s']) : date('Y-m-d H:i:s', time() - 24 * 3600)));
define('DEF_END_TIME', isset($_GET['end']) ? urldecode($_GET['end']) : (isset($_GET['e']) ? urldecode($_GET['e']) : date('Y-m-d H:i:s')));

const REQUEST_HEADER = 'Authorization: Basic Y2xpZW50OmpiajBRSEtfZWZrX2FlcV9tdXQ=';
const HOUR_URI = ATCOS_IP . ':' . ATCOS_PORT . '/working/hour/still';
const HOUR_URI_END = ATCOS_IP . ':' . ATCOS_PORT . '/working/hour/ended';
const RWY_URI = ATCOS_IP . ':' . ATCOS_PORT . '/runway/mode/recent';
const USER_URI = ATCOS_IP . ':' . ATCOS_PORT . '/user/terminal';
const SECTOR_URI = ATCOS_IP . ':' . ATCOS_PORT . '/seat/sector/entire';

const DEF_ICAO_CODES = ['ZUUU', 'ZUTF', 'ZUMY'];

// orgId对应信息
define('ORG_INFO', param('ATCOS_ORG_INFO'));

define('USERS', param('ATCOS_USERS_CONTENT'));

output(agent_atcos_load());

/**
 * main function
 */
function agent_atcos_load($module = MODULE) {
  switch ($module) {

  // all
  case '*':return ['sector' => load_sectors(), 'hour' => load_hours(), 'runway' => load_rwy(), 'user' => load_users(), 'sectorHistory' => update_sector_record(), 'runwayHistory' => update_runway_record()];

  // sector related
  case 'sector':return ['sector' => load_sectors(), 'sectorHistory' => update_sector_record()];
  case 'sectorOnly':return ['sector' => load_sectors()];
  case 'sectorHistory':return ['sectorHistory' => update_sector_record()];
  case 'hour':return ['hour' => load_hours()];

  // runway related
  case 'runway':return ['runway' => load_rwy(), 'runwayHistory' => update_runway_record()];
  case 'runwayOnly':return ['runway' => load_rwy()];
  case 'runwayHistory':return ['runwayHistory' => update_runway_record()];

  // user related
  case 'user':return ['user' => load_users()];

  // null
  default:return ['Error, invalid module provided!'];
  }
}

/**
 * following functions are main entry for each module
 */

function load_hours($start = DEF_START_TIME, $end = DEF_END_TIME) {
  $tx = param('ATCOS_HOUR_TIMESTAMP_SEND');
  $rx = param('ATCOS_HOUR_IMESTAMP_RECIVE');
  $min = param('ATCOS_HOUR_INTERVAL_MIN');
  $max = param('ATCOS_HOUR_INTERVAL_MAX');
  $valid = timestamp_verify($tx, $rx, $min, $max);
  $status = FORCE ? 9 : $valid['status'];
  $msg = (FORCE ? 'Forced. ' : '') . $valid['msg'];
  $content = [];
  $sqls = [];
  $responses = [];
  $result = false;
  if ($status > 0) {
    $timestamp = timestamp();
    param('ATCOS_HOUR_TIMESTAMP_SEND', $timestamp);
    param('ATCOS_HOUR_TIME_SEND', date('Y-m-d H:i:s'));
    if ($status == 2) {
      param('ATCOS_HOUR_TIMESTAMP_RECIVE', $timestamp - 1);
    }

    $response = request_hours_end($start, $end);

    if ($response || is_array($response)) {
      foreach ($response as $cell) {
        $recordID = $cell['id'];
        $userId = $cell['userId'];
        $userName = $cell['userName'];
        $seatCode = $cell['seatCode'];
        $logicSectorCode = $cell['logicSectorCode'];
        $sectorCodes = $cell['sectorCodes'];
        $startTime = $cell['startTime'];
        $endTime = $cell['endTime'];
        $seatRoleId = $cell['seatRoleId'];
        $seatRole = seat_ids_translate('seatRoleId', $seatRoleId);
        $seatPostId = $cell['seatPostId'];
        $seatPost = seat_ids_translate('seatPostId', $seatPostId);
        $qualificationId = $cell['qualificationId'];
        $qualification = seat_ids_translate('qualificationId', $qualificationId);
        $controlLevelId = $cell['controlLevelId'];
        $controlLevel = seat_ids_translate('controlLevelId', $controlLevelId);
        // $orgId = 4; // 不再识别orgId
        $orgId = get_user_org($userId);

        $sqls[] = "REPLACE INTO `2kt_seat_hours`(`recordID`, `userName`, `userId`, `startTime`, `endTime`, `seatCode`, `logicSectorCode`, `sectorCodes`, `seatRole`, `seatRoleId`, `seatPost`, `seatPostId`, `qualification`, `qualificationId`, `controlLevel`, `controlLevelId`, `orgId`) VALUES ({$recordID},'{$userName}',{$userId},'{$startTime}','{$endTime}','{$seatCode}','{$logicSectorCode}','{$sectorCodes}','{$seatRole}',{$seatRoleId},'{$seatPost}',{$seatPostId},'{$qualification}',{$qualificationId},'{$controlLevel}',{$controlLevelId},{$orgId})";
        $content[] = $cell;
      }
    }

    param('ATCOS_HOUR_TIMESTAMP_RECIVE', timestamp());
    param('ATCOS_HOUR_TIME_RECIVE', date('Y-m-d H:i:s'));
    $result = !in_array(false, exec_sql_array($sqls));
  }

  // 标准情况下的输出
  $output = [
    'code' => $status,
    'result' => $result,
  ];

  // Verbose额外输出
  VERBOSE ? $output['msg'] = $msg : null;
  VERBOSE ? $output['content'] = $content : null;
  VERBOSE ? $output['sqls'] = $sqls : null;
  VERBOSE ? $output['response'] = $response : null;

  return $output;
}

function load_rwy($codes = DEF_ICAO_CODES) {
  $res = [];
  $tx = param('ATCOS_RWY_MODE_TIMESTAMP_SEND');
  $rx = param('ATCOS_RWY_MODE_TIMESTAMP_RECIVE');
  $min = param('ATCOS_RWY_MODE_INTERVAL_MIN');
  $max = param('ATCOS_RWY_MODE_INTERVAL_MAX');
  $valid = timestamp_verify($tx, $rx, $min, $max);
  $status = FORCE ? 9 : $valid['status'];
  $res['code'] = $status;
  $msg = (FORCE ? 'Forced. ' : '') . $valid['msg'];
  VERBOSE ? $res['msg'] = $msg : null;
  if ($status > 0) {
    $timestamp = timestamp();
    param('ATCOS_RWY_MODE_TIMESTAMP_SEND', $timestamp);
    param('ATCOS_RWY_MODE_TIME_SEND', date('Y-m-d H:i:s'));
    if ($status == 2) {
      // 如果已经大约 MAX 则重置为等待回复的状态
      param('ATCOS_RWY_MODE_TIMESTAMP_RECIVE', $timestamp - 1);
    }
    foreach ($codes as $code) {
      $data = request_runways($code);
      $res[$code] = $data;
      param('ATCOS_RWY_MODE_CODE_' . $code, $data);
    }
    param('ATCOS_RWY_MODE_TIMESTAMP_RECIVE', timestamp());
    param('ATCOS_RWY_MODE_TIME_RECIVE', date('Y-m-d H:i:s'));
  }
  return $res;
}

function load_users() {
  // {"orgId":13,"fullName":"吴量","code":"20060012"}
  $res = [];
  $tx = param('ATCOS_USERS_TIMESTAMP_SEND');
  $rx = param('ATCOS_USERS_TIMESTAMP_RECIVE');
  $min = param('ATCOS_USERS_INTERVAL_MIN');
  $max = param('ATCOS_USERS_INTERVAL_MAX');
  $valid = timestamp_verify($tx, $rx, $min, $max);
  $status = FORCE ? 9 : $valid['status'];
  $res['code'] = $status;
  $msg = (FORCE ? 'Forced. ' : '') . $valid['msg'];
  VERBOSE ? $res['msg'] = $msg : null;
  if ($status > 0) {
    $timestamp = timestamp();
    param('ATCOS_USERS_TIMESTAMP_SEND', $timestamp);
    param('ATCOS_USERS_TIME_SEND', date('Y-m-d H:i:s'));
    if ($status == 2) {
      // 如果已经大约 MAX 则重置为等待回复的状态
      param('ATCOS_USERS_TIMESTAMP_RECIVE', $timestamp - 1);
    }
    $data = request_users();
    $data_filtered = [];
    foreach ($data as $cell) {
      if (is_numeric($cell['code'])) {
        $orgInfo = get_org_info($cell['orgId']);
        if ($orgInfo && $orgInfo['orgGroup'] == 'TMA') {
          $cell['orgName'] = $orgInfo['orgName'];
          $data_filtered[] = $cell;
        }
      }
    }
    $data = $data_filtered;
    $data2 = [];
    foreach (ORG_INFO as $org) {
      if ($org['orgGroup'] == 'TMA') {
        $group = [
          'orgName' => $org['orgName'],
          'orgId' => $org['orgId'],
          'users' => [],
        ];
        foreach ($data as $cell) {
          if ($cell['orgId'] == intval($org['orgId'])) {
            $group['users'][] = ['fullName' => $cell['fullName'], 'code' => $cell['code']];
          }
        }
        $data2[] = $group;
      }
    }
    $res['count'] = count($data);
    VERBOSE ? $res['data'] = $data : null;
    param('ATCOS_USERS_CONTENT', $data);
    param('ATCOS_USERS_CONTENT_GROUPED', $data2);
    param('ATCOS_USERS_TIMESTAMP_RECIVE', timestamp());
    param('ATCOS_USERS_TIME_RECIVE', date('Y-m-d H:i:s'));
  }
  return $res;
}

function load_sectors() {
  $res = [];
  $sql = [];
  $tx = param('ATCOS_SECTOR_TIMESTAMP_SEND');
  $rx = param('ATCOS_SECTOR_TIMESTAMP_RECIVE');
  $min = param('ATCOS_SECTOR_INTERVAL_MIN');
  $max = param('ATCOS_SECTOR_INTERVAL_MAX');
  $verify_result = timestamp_verify($tx, $rx, $min, $max);
  $status = FORCE ? 9 : $verify_result['status'];
  $msg = (FORCE ? 'Forced! ' : '') . $verify_result['msg'];
  // VERBOSE ? $res['status'] = $status : null;
  // VERBOSE ? $res['msg'] = $msg : null;
  $res['status'] = $status;
  $res['msg'] = $msg;

  // status > 0 时才进行后续操作
  if ($status > 0) {
    $timestamp = timestamp();
    param('ATCOS_SECTOR_TIMESTAMP_SEND', $timestamp);
    param('ATCOS_SECTOR_TIME_SEND', date('Y-m-d H:i:s'));
    if ($status == 2) {
      // 如果已经大约 MAX 则重置为等待回复的状态
      param('ATCOS_SECTOR_TIMESTAMP_RECIVE', $timestamp - 1);
    }

    // 获取扇区信息
    $data1 = request_sectors();
    $seats = [];
    if (isset($data1) && is_array($data1) && count($data1) > 0) {
      foreach ($data1 as $cell) {
        // 如果还未添加对应seat, 新建一个seatCode为key的数组
        if (!isset($seats[$cell['seatCode']])) {
          $org_info = get_org_info($cell['orgId']);
          $seats[$cell['seatCode']] = [
            'seatCode' => $cell['seatCode'],
            'logicSectorCode' => $cell['logicSectorCode'],
            'sectorCodes' => [],
            'users' => [],
            'orgId' => $cell['orgId'] ? $cell['orgId'] : 'NULL',
            'orgName' => $org_info ? $org_info['orgName'] : '',
            'orgGroup' => $org_info ? $org_info['orgGroup'] : '',
          ];
        }
        // 如果新检索到的logicSectorCode不为空, 则覆盖原有logicSectorCode
        if ($cell['logicSectorCode'] != '') {
          $seats[$cell['seatCode']]['logicSectorCode'] = $cell['logicSectorCode'];
        }
        // 对应seat的sectorCodes中添加sectorCode
        $seats[$cell['seatCode']]['sectorCodes'][] = $cell['sectorCode'];
      }
    }

    // 获取打卡信息，用于：1、更新席位信息；2、更新小时数信息
    $data2 = request_hours_still();
    // $hour = [];
    if (isset($data2) && is_array($data2) && count($data2) > 0) {
      $sql[] = "DELETE FROM `2kt_seat_hours` WHERE `endTime` IS NULL";
      foreach ($data2 as $cell) {
        // $hour[] = $cell;
        $recordID = $cell['id'];
        $userId = $cell['userId'];
        $userName = $cell['userName'];
        $seatCode = $cell['seatCode'];
        $logicSectorCode = $cell['logicSectorCode'];
        $sectorCodes = $cell['sectorCodes'];
        $startTime = $cell['startTime'];
        $endTime = $cell['endTime'];
        $seatRoleId = $cell['seatRoleId'];
        $seatRole = seat_ids_translate('seatRoleId', $seatRoleId);
        $seatPostId = $cell['seatPostId'];
        $seatPost = seat_ids_translate('seatPostId', $seatPostId);
        $qualificationId = $cell['qualificationId'];
        $qualification = seat_ids_translate('qualificationId', $qualificationId);
        $controlLevelId = $cell['controlLevelId'];
        $controlLevel = seat_ids_translate('controlLevelId', $controlLevelId);
        // $orgId = 4; // 不再判断orgId
        $orgId = get_user_org($userId);

        // 更新小时数表

        $sql[] = "REPLACE INTO `2kt_seat_hours`(`recordID`, `userName`, `userId`, `startTime`, `seatCode`, `logicSectorCode`, `sectorCodes`, `seatRole`, `seatRoleId`, `seatPost`, `seatPostId`, `qualification`, `qualificationId`, `controlLevel`, `controlLevelId`, `orgId`) VALUES ({$recordID},'{$userName}',{$userId},'{$startTime}','{$seatCode}','{$logicSectorCode}','{$sectorCodes}','{$seatRole}',{$seatRoleId},'{$seatPost}',{$seatPostId},'{$qualification}',{$qualificationId},'{$controlLevel}',{$controlLevelId},{$orgId})";

        // 基于打卡数据，更新席位信息
        if (!isset($seats[$seatCode])) {
          // 未添加该席位
          $default_org_id = 4;
          // 通过打卡数据添加的seat, orgId默认为4
          $org_info = get_org_info($default_org_id);
          $seats[$seatCode] = [
            'seatCode' => $seatCode,
            'logicSectorCode' => $logicSectorCode,
            /**
             * 'sectorCodes' => $sectorCodes,
             * 不再通过此数据更新扇区信息
             */
            'sectorCodes' => [],
            'users' => [],
            'orgId' => $default_org_id,
            'orgName' => $org_info ? $org_info['orgName'] : '',
            'orgGroup' => $org_info ? $org_info['orgGroup'] : '',
          ];
        }
        /**
         * $seats[$seatCode]['sectorCodes'] = $sectorCodes;
         * 不再通过此数据更新扇区信息
         */
        $seats[$seatCode]['users'][] = [
          'userName' => $userName,
          'userId' => $userId,
          'startTime' => $startTime,
          'seatRole' => $seatRole,
          'seatRoleId' => $seatRoleId,
          'seatPost' => $seatPost,
          'seatPostId' => $seatPostId,
          'qualification' => $qualification,
          'qualificationId' => $qualificationId,
          'controlLevel' => $controlLevel,
          'controlLevelId' => $controlLevelId,
        ];
      }
    }

    // 更新seatStatus表
    // activeCodes: 当前有扇区或打卡记录的列表，列表以外的清空扇区以及人员
    $activeCodes = [];
    ksort($seats); // 根据seatCode排序
    foreach ($seats as $code => $cell) {
      $activeCodes[] = $code;
      $seatName = $cell['seatCode'];
      $logicSectorCode = $cell['logicSectorCode'];
      sort($cell['sectorCodes']); // 根据sectorCode排序
      $sectorCodes = json_stringify($cell['sectorCodes']);
      $users = json_stringify($cell['users']);
      $orgID = $cell['orgId'];
      $orgName = $cell['orgName'];
      $orgGroup = $cell['orgGroup'];
      $sql_i = "INSERT INTO `2kt_seat_status`(`seatName`, `logicSectorCode`, `sectorCodes`, `users`, `orgID`, `orgName`, `orgGroup`) VALUES ('{$seatName}','{$logicSectorCode}','{$sectorCodes}','{$users}',{$orgID},'{$orgName}','{$orgGroup}') ON DUPLICATE KEY UPDATE `logicSectorCode`='$logicSectorCode',`sectorCodes`='{$sectorCodes}',`users`='{$users}'";
      // echo $code . PHP_EOL . $sql_i . PHP_EOL . PHP_EOL;
      $sql[] = $sql_i;
    }
    $activeCodes = implode("','", $activeCodes);
    // 清空未查询到的扇区信息
    // , `logicSectorCode` = ''
    $sql[] = "UPDATE `2kt_seat_status` SET `users` = '[]', `sectorCodes`='[]' WHERE `seatName` NOT IN ('{$activeCodes}')";
    // VERBOSE ? $res['sql'] = $sql : null;
    /* 用于测试的代码
    var_dump($sql);
    foreach ($sql as $i) {
    echo $i . PHP_EOL;
    var_dump(exec_sql($i));
    echo PHP_EOL . PHP_EOL;
    }
    $result = [];
     */
    if (LOG) {
      logfile("AGENT_ATCOS_SECTORS", json_stringify($sql));
    }
    $result = exec_sql_array($sql);
    // VERBOSE ? $res['result'] = $result : null;

    $success = !in_array(false, $result);
    $res['success'] = $success;

    if (!$success) {
      $failed = [];
      foreach ($result as $key => $value) {
        if (!$value) {
          $failed[] = $sql[$key];
        }
      }
      $res['failed'] = $failed;
    }

    VERBOSE ? $res['data1'] = $data1 : null;
    VERBOSE ? $res['data2'] = $data2 : null;
    VERBOSE ? $res['seats'] = $seats : null;
    // VERBOSE ? $res['hour'] = $hour : null;

    // 保存更新时间
    param('ATCOS_SECTOR_TIMESTAMP_RECIVE', timestamp());
    param('ATCOS_SECTOR_TIME_RECIVE', date('Y-m-d H:i:s'));
  }
  return $res;
}

/**
 * 以下为元始请求函数
 */

function request_runways($icao) {
  $curl = curl_init();
  curl_setopt_array($curl, array(
    CURLOPT_URL => RWY_URI . '?airport=' . $icao,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_ENCODING => '',
    CURLOPT_MAXREDIRS => 10,
    CURLOPT_TIMEOUT => 0,
    CURLOPT_FOLLOWLOCATION => true,
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_HTTPHEADER => array(REQUEST_HEADER),
  ));
  $response = curl_exec($curl);
  curl_close($curl);

  if ($response == '') {
    return null;
  } else {
    $response = json_parse($response);
    if ($response && $response['code'] == 0) {
      return $response['data'];
    } else {
      return null;
    }
  }
}

function request_users() {
  $curl = curl_init();

  curl_setopt_array($curl, array(
    CURLOPT_URL => USER_URI,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_ENCODING => '',
    CURLOPT_MAXREDIRS => 10,
    CURLOPT_TIMEOUT => 0,
    CURLOPT_FOLLOWLOCATION => true,
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_HTTPHEADER => array(REQUEST_HEADER),
  ));

  $response = curl_exec($curl);

  if ($response == '') {
    return null;
  } else {
    $response = json_parse($response);
    if ($response && $response['code'] == 0) {
      return $response['data'];
    } else {
      return null;
    }
  }
}

function request_hours_still() {
  $curl = curl_init();

  curl_setopt_array($curl, array(
    CURLOPT_URL => HOUR_URI . '?orgId=4',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_ENCODING => '',
    CURLOPT_MAXREDIRS => 10,
    CURLOPT_TIMEOUT => 0,
    CURLOPT_FOLLOWLOCATION => true,
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_HTTPHEADER => array(REQUEST_HEADER),
  ));

  $response = curl_exec($curl);
  curl_close($curl);
  // logfile("request_hours_still({$orgid})", $response);
  if ($response == '') {
    return [];
  } else {
    $response = json_parse($response);
    if ($response && $response['code'] == 0) {
      return $response['data'];
    } else {
      return [];
    }
  }
}

function request_hours_end($start, $end) {
  $curl = curl_init();
  $startu = urlencode($start);
  $endu = urlencode($end);
  curl_setopt_array($curl, array(
    CURLOPT_URL => HOUR_URI_END . '?startTime=' . $startu . '&endTime=' . $endu . '&orgId=4',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_ENCODING => '',
    CURLOPT_MAXREDIRS => 10,
    CURLOPT_TIMEOUT => 0,
    CURLOPT_FOLLOWLOCATION => true,
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_HTTPHEADER => array(REQUEST_HEADER),
  ));

  $response = curl_exec($curl);
  curl_close($curl);

  if ($response == '') {
    return [];
  } else {
    $response = json_parse($response);
    if ($response && $response['code'] == 0) {
      return $response['data'];
    } else {
      return [];
    }
  }
}

function request_sectors() {

  $curl = curl_init();

  curl_setopt_array($curl, array(
    CURLOPT_URL => SECTOR_URI,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_ENCODING => '',
    CURLOPT_MAXREDIRS => 10,
    CURLOPT_TIMEOUT => 0,
    CURLOPT_FOLLOWLOCATION => true,
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_HTTPHEADER => array(REQUEST_HEADER),
  ));

  $response = curl_exec($curl);

  curl_close($curl);

  if ($response == '') {
    return [];
  } else {
    $response = json_parse($response);
    if ($response && $response['code'] == 0 && is_array($response['data'])) {
      return $response['data'];
    } else {
      return [];
    }
  }

}

/**
 * following functions are used as utils for internal operations
 */

function timestamp_verify($tx, $rx, $min, $max) {
  $t0 = timestamp();
  if ($t0 - $rx >= $max) {
    return ['status' => 2, 'msg' => 'Need to load, exceeded max interval.'];
  } elseif ($tx > $rx) {
    return ['status' => -1, 'msg' => 'No need to load, waiting for response.'];
  } elseif ($t0 - $rx < $min) {
    $val = $t0 - $rx;
    return ['status' => 0, 'msg' => "No need to load ({$t0}-{$rx}={$val}<{$min})"];
  } else {
    return ['status' => 1, 'msg' => 'Need to load.'];
  }
}

function seat_ids_translate($key, $value) {
  if ($key == 'seatRoleId') {
    if ($value == 1) {
      return '教员';
    }
    if ($value == 2) {
      return '放单';
    }
    if ($value == 3) {
      return '学员';
    }
  }
  if ($key == 'seatPostId') {
    if ($value == 1) {
      return '管制岗';
    }
    if ($value == 2) {
      return '协调岗';
    }
    if ($value == 3) {
      return '第三岗';
    }
    if ($value == 4) {
      return '带班主任岗';
    }
    if ($value == 5) {
      return '任管制岗';
    }
    if ($value == 6) {
      return '流量管理岗';
    }
    if ($value == 7) {
      return '带班主任岗2';
    }
  }
  if ($key == 'qualificationId') {
    if ($value == 1) {
      return '全放单';
    }
    if ($value == 2) {
      return '部分放单';
    }
    if ($value == 3) {
      return '未放单';
    }
  }
  if ($key == 'controlLevelId') {
    if ($value == 1) {
      return '一级';
    }
    if ($value == 2) {
      return '二级';
    }
    if ($value == 3) {
      return '三级';
    }
    if ($value == 4) {
      return '四级';
    }
    if ($value == 5) {
      return '五级';
    }
    if ($value == 6) {
      return '见习';
    }
  }
}

function get_org_info($org_id) {
  /**
   * 根据orgId查询科室信息
   * 需要对$org_id和$org['orgId']进行int数值转换后再进行比较
   * [{"orgId":"4","orgName":"终端管制室","orgGroup":"TMA"},eg...]
   */
  foreach (ORG_INFO as $org) {
    if (intval($org['orgId']) == intval($org_id)) {
      return $org;
    }
  }
  return null;
}

function get_user_org($code, $full = false) {
  /**
   * 用于根据工牌号查询科室信息
   * full = false 返回orgId
   * full = true 返回orgInfo
   */
  foreach (USERS as $user) {
    if ($user['code'] == $code) {
      if ($full) {
        return get_org_info($user['orgId']);
      } else {
        return $user['orgId'];
      }
    }
  }
  if ($full) {
    return null;
  } else {
    return 0;
  }
}

function update_user_table($data) {}

function update_sector_record() {
  $sql = "CREATE TABLE IF NOT EXISTS `2kt_sector_record` (`number` INT(16) NOT NULL AUTO_INCREMENT , `startTime` DATETIME NULL DEFAULT NULL , `endTime` DATETIME NULL DEFAULT NULL , `count` INT(4) NULL DEFAULT NULL , `direction` VARCHAR(8) NULL DEFAULT NULL , `content` TEXT NULL DEFAULT NULL , PRIMARY KEY (`number`)) ENGINE = InnoDB;";
  exec_sql($sql);
  $output = [];
  // =================================================================
  // 新纪录的内容
  $sql = "SELECT `seatName`,`sectorCodes`FROM `2kt_seat_status` WHERE `orgGroup` = 'TMA' AND `sectorYes` = 1 AND `sectorCodes` IS NOT NULL AND `sectorCodes` != '[]' AND `users` IS NOT NULL AND `users` != '' ORDER BY `seatName` ASC";
  $current_status = exec_sql($sql);
  // 如果未查找到
  if (!$current_status || !is_array($current_status) || count($current_status) == 0) {
    $output['status'] = -1;
    $output['msg'] = 'Failed to load current status';
    VERBOSE ? $output['sql'] = $sql : null;
    return $output;
  }
  // 转换为记录的content内容：['TM01'=>['AP12','AP7L','AP7R']]
  $current_status = query_parse($current_status);
  $current_status_content = [];
  foreach ($current_status as $cell) {
    $current_status_content[$cell['seatName']] = $cell['sectorCodes'];
  }
  $current_status_content_json = json_stringify($current_status_content);
  // =================================================================
  // 查找上一条记录
  // $sql = "SELECT * FROM `2kt_sector_record` WHERE `endTime` IS NULL ORDER BY `startTime` DESC LIMIT 1";
  // 不再根据 endTime 判断是否为上一条记录，仅根据 number 数值从大到小判断
  $sql = "SELECT * FROM `2kt_sector_record` ORDER BY `number` DESC LIMIT 1";
  $last_record = exec_sql($sql);
  $last_record_content_json = "";
  $last_record_number = -1;
  $changed = false;
  if (!$last_record || !is_array($last_record) || count($last_record) == 0) {
    // 如果没有查找到endTime=NULL的记录，则changed=true，需要记录
    // 如果没有查找到上一条记录
    $changed = true;
  } else {
    // 否则（查找到上一条记录）
    // 判断是否发生改变
    // $last_record_content_json = json_stringify(json_parse($last_record[0]['content'])); // JSON字符串
    $last_record_number = $last_record[0]['number'];
    $last_record_content_json = $last_record[0]['content']; // JSON字符串
    // 如果JSON字符串不一致，则changed=true，需要记录
    $changed = $last_record_content_json != $current_status_content_json;
  }
  $output['chenged'] = $changed;
  // =================================================================
  // 如果发生改变
  if ($changed) {
    $sql = [];
    $datetime = date('Y-m-d H:i:s');
    if ($last_record_number > -1) {
      // 如果存在一条未结束的记录，更新endTime
      $sql[] = "UPDATE `2kt_sector_record` SET `endTime` = '$datetime' WHERE `number` = {$last_record_number}";
    }
    // 插入一条新纪录
    $count = count($current_status_content);
    $modeZUUU = param('ATCOS_RWY_MODE_CODE_ZUUU');
    $modeZUTF = param('ATCOS_RWY_MODE_CODE_ZUTF');
    $direction = substr($modeZUUU, 0, 1) . substr($modeZUTF, 0, 1);
    $sql[] = "INSERT INTO `2kt_sector_record` (`startTime`,`count`,`direction`,`content`) VALUES ('{$datetime}',{$count},'{$direction}','{$current_status_content_json}')";
    $result = !in_array(false, exec_sql_array($sql));
    $output['result'] = $result;
    VERBOSE ? $output['current'] = $current_status_content : null;
    VERBOSE ? $output['last'] = json_parse($last_record_content_json) : null;
  }
  // @20240814
  // 查找endTime为NULL的行，并将endTime更新为下一行的startTime

  $no_end_rows = exec_sql("SELECT `number` FROM `2kt_sector_record` WHERE `endTime` IS NULL");
  if ($no_end_rows && is_array($no_end_rows) && count($no_end_rows) > 0) {
    // 输出结果
    $result_no_end_fix = [
      'count' => count($no_end_rows),
      'fixed' => 0,
    ];
    // 遍历所有endTime为NULL的行
    foreach ($no_end_rows as $row) {
      // 当前行的number
      $target_row_number = intval($row['number']);
      // 下一行的number
      $next_row_number = $target_row_number + 1;
      // 下一行的startTime
      $next_row = exec_sql("SELECT `startTime` FROM 2kt_sector_record WHERE `number` = {$next_row_number}");
      if ($next_row && is_array($next_row) && count($next_row) > 0) {
        $next_row = $next_row[0];
        $start_time_next_row = $next_row['startTime'];
        // 更新当前行的endTime为下一行的startTime
        $result_no_end_target = exec_sql("UPDATE `2kt_sector_record` SET `endTime` = '{$start_time_next_row}' WHERE `number` = {$target_row_number}");
        if ($result_no_end_target) {
          // 累计已更新行数
          $result_no_end_fix['fixed']++;
        }
      }
    }
    $output['noEndFix'] = $result_no_end_fix;
  }
  return $output;
}

function update_runway_record() {
  // CREATE TABLE IF NOT EXISTS
  exec_sql("CREATE TABLE IF NOT EXISTS `2kt_runway_record` (
    `number` int(8) NOT NULL AUTO_INCREMENT,
    `icao` varchar(8) DEFAULT NULL,
    `startTime` datetime DEFAULT NULL,
    `endTime` datetime DEFAULT NULL,
    `code` varchar(8) DEFAULT NULL,
    `direction` varchar(4) DEFAULT NULL,
    `count` int(4) DEFAULT NULL,
    `countDep` int(4) DEFAULT NULL,
    `countArr` int(4) DEFAULT NULL,
    PRIMARY KEY (`number`)
   ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci");

  $output = [];
  $datetime = date('Y-m-d H:i:s');
  $sql = [];
  foreach (DEF_ICAO_CODES as $icao) {
    $changed = false;
    $last_record_number = -1;
    $current_code = param('ATCOS_RWY_MODE_CODE_' . $icao);
    // =================================================================
    // 查找上一条记录
    // $last_record = exec_sql("SELECT * FROM `2kt_runway_record` WHERE `icao` = '{$icao}' AND `endTime` IS NULL ORDER BY `number` LIMIT 1");
    // 不再根据 endTime 判断是否为上一条记录，仅根据 number 数值从大到小判断
    $last_record = exec_sql("SELECT * FROM `2kt_runway_record` WHERE `icao` = '{$icao}' ORDER BY `number` DESC LIMIT 1");
    if ($last_record && is_array($last_record) && count($last_record) > 0) {
      // 如果检索到已有记录，检查是否改变
      $last_code = $last_record[0]['code'];
      if ($last_code != $current_code) {
        $last_record_number = $last_record[0]['number'];
        $changed = true;
      }
    } else {
      // 如果为检索到已有记录，则 changed = true
      $changed = true;
    }
    if ($changed) {
      if ($last_record_number > -1) {
        $sql[] = "UPDATE `2kt_runway_record` SET `endTime`='{$datetime}' WHERE `number` = '{$last_record_number}'";
      }
      $code_chars = str_split($current_code);
      $direction = '';
      $count_dep = 0;
      $count_arr = 0;
      $count = 0;
      foreach ($code_chars as $index => $char) {
        if (is_numeric($char)) {
          $val = intval($char);
          if ($val > 0) {
            $count++;
            if ($val == 1 || $val == 3) {
              $count_dep++;
            }
            if ($val == 2 || $val == 3) {
              $count_arr++;
            }
          }
        } else {
          $direction = $char;
        }
      }
      $sql[] = "INSERT INTO `2kt_runway_record` (`icao`,`startTime`,`code`,`direction`,`count`,`countDep`,`countArr`) VALUES ('{$icao}','{$datetime}','{$current_code}','{$direction}','{$count}','{$count_dep}','{$count_arr}')";
      VERBOSE ? ($output[$icao] = $current_code) : null;
    }
  }
  $result = exec_sql_array($sql);
  $changed_count = count($sql);
  $success = $result && !in_array(false, $result);
  $output['changed'] = $changed_count;
  $changed_count ? ($output['success'] = $success) : null;
  (VERBOSE && $changed_count && !$success) ? ($output['sql'] = $sql) : null;
  return $output;
}